package utils

import (
	"github.com/cloudwego/hertz/pkg/common/hlog"
	"github.com/gocarina/gocsv"
	"github.com/mssola/useragent"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

var onceFunc = sync.OnceFunc(func() {
	ticker := time.NewTicker(24 * 30 * time.Hour)
	if len(phoneData) == 0 {
		dir, _ := os.Getwd()
		fileDir := filepath.Join(dir, "user_agent")
		_, err := os.Stat(fileDir)
		if err != nil {
			_ = os.MkdirAll(fileDir, os.ModePerm)
		}
		getPhoneDataRemote()
	}
	go func() {
		select {
		case <-ticker.C:
			getPhoneDataRemote()
		}
	}()
})

type UserAgentRes struct {
	OSName     string //操作系统名称
	OSVersion  string //操作系统版本
	PhoneBrand string //手机品牌
	PhoneModel string //手机型号
}

type PhoneData struct {
	Model      string `csv:"model"`
	Dtype      string `csv:"dtype"`
	Brand      string `csv:"brand"`
	BrandTitle string `csv:"brand_title"`
	Code       string `csv:"code"`
	CodeAlias  string `csv:"code_alias"`
	ModelName  string `csv:"model_name"`
	VerName    string `csv:"ver_name"`
}

var phoneData []*PhoneData

// GetUserAgent 获取用户设备信息获取手机型号等信息
func GetUserAgent(userAgent string) UserAgentRes {
	ua := useragent.New(userAgent)
	var brand string
	var model string
	osName := ua.OS()
	osVersion := ""
	if strings.Contains(osName, " ") {
		arrOS := strings.Split(osName, " ")
		if len(arrOS) > 1 {
			osName = arrOS[0]
			osVersion = arrOS[1]
		}
	}
	phoneData = getPhoneData()
	for _, v := range phoneData {
		if v.Model == ua.Model() {
			brand = v.BrandTitle
			model = v.ModelName
			break
		}
	}
	return UserAgentRes{
		OSName:     osName,
		OSVersion:  osVersion,
		PhoneBrand: brand,
		PhoneModel: model,
	}
}

// 从本地获取手机模型信息
func getPhoneData() []*PhoneData {
	onceFunc()
	if len(phoneData) == 0 {
		dir, _ := os.Getwd()
		file, err := os.Open(filepath.Join(dir, "user_agent", "models.csv"))
		if err != nil {
			return nil
		}
		defer file.Close()

		var res []*PhoneData
		err = gocsv.Unmarshal(file, &res)
		if err != nil {
			return nil
		}
		phoneData = res
	}
	return phoneData
}

// 从远程获取手机模型信息
func getPhoneDataRemote() {
	url := "https://raw.githubusercontent.com/KHwang9883/MobileModels/master/scripts/models.csv"
	res, err := http.Get(url)
	if err != nil {
		hlog.Errorf("http请求获取远程手机模型信息错误%s", err.Error())
		return
	} else {
		defer func() {
			err = res.Body.Close()
			if err != nil {
				hlog.Errorf("关闭获取手机模型http请求错误%s", err.Error())
				return
			}
		}()
		dir, _ := os.Getwd()
		file, err := os.OpenFile(filepath.Join(dir, "user_agent", "models.csv"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0666)
		if err != nil {
			hlog.Errorf("创建或者打开models.csv文件错误%s", err.Error())
			return
		} else {
			defer func() {
				err := file.Close()
				if err != nil {
					hlog.Errorf("关闭csv文件错误%s", err.Error())
					return
				}
			}()
			_, err = io.Copy(file, res.Body)
			if err != nil {
				hlog.Errorf("手机模型远程内容写入文件错误%s", err.Error())
				return
			}
			_, err = file.Seek(0, 0)
			if err != nil {
				hlog.Errorf("重置文件指针错误%s", err.Error())
				return
			}
			var phoneDataTemp []*PhoneData
			err = gocsv.Unmarshal(file, &phoneDataTemp)
			if err != nil {
				hlog.Errorf("获取手机模型反序列化错误%s", err.Error())
				return
			}
			phoneData = phoneDataTemp
		}
	}
}
